#include "9bit_spi.h"


uint8_t count=0;

uint8_t lut_v[15]   = {0x4A,0x4A,0x01,0x8A,0x8A,0x01,0x4A,0x4A,0x01,0x8A,0x8A,0x01,0x81,0x81,0x01};
uint8_t lut_kk[15]  = {0x8A,0x8A,0x01,0x8A,0x8A,0x01,0x4A,0x4A,0x01,0x4A,0x4A,0x01,0x81,0x81,0x01};
uint8_t lut_ww[15]  = {0x4A,0x4A,0x01,0x4A,0x4A,0x01,0x8A,0x8A,0x01,0x8A,0x8A,0x01,0x81,0x81,0x01};

/*int num_1[14] = {14,7,  12,4,   11,7,   13,5,   15,2,   15,1,   14,5};
int num_2[14] = {13,2,  12,6,   9,2,    10,4,   10,3,   12,5,   10,5};
int num_3[14] = {13,1,  11,0,   9,5,    5,4,    9,1,    12,7,   10,7};
int num_4[14] = {13,0,  11,2,   7,0,    5,3,    9,6,    11,1,   10,6};
int num_5[14] = {15,7,  14,1,   14,0,   0,1,    15,4,   15,5,   15,6};
int num_6[14] = {13,3,  13,7,   13,6,   0,0,    14,2,   14,4,   14,3};
int num_7[14] = {11,6,  11,5,   12,2,   1,7,    12,0,   12,1,   12,3};
int num_8[14] = {8,1,   8,5,    8,6,    8,3,    9,4,    9,3,    9,7};
int num_9[14] = {6,3,   6,6,    6,7,    6,0,    7,5,    7,4,    6,5};
int num_10[14] ={4,2,   4,3,    1,4,    1,5,    1,6,    4,1,    3,6};
int num_11[14] ={4,5,   4,6,    1,1,    1,2,    1,3,    4,4,    4,5};
int num_12[14] ={3,3,   3,5,    2,5,    2,6,    2,7,    4,7,    2,0};
int num_13[14] ={7,6,   6,1,    5,0,    5,2,    5,1,    6,2,    6,4};*/

static int num_segments[13][14] = {
        {14,7,  12,4,   11,7,   13,5,   15,2,   15,1,   14,5},
        {13,2,  12,6,   9,2,    10,4,   10,3,   12,5,   10,5},
        {13,1,  11,0,   9,5,    5,4,    9,1,    12,7,   10,7},
        {13,0,  11,2,   7,0,    5,3,    9,6,    11,1,   10,6},
        {15,7,  14,1,   14,0,   0,1,    15,4,   15,5,   15,6},
        {13,3,  13,7,   13,6,   0,0,    14,2,   14,4,   14,3},
        {11,6,  11,5,   12,2,   1,7,    12,0,   12,1,   12,3},
        {8,1,   8,5,    8,6,    8,3,    9,4,    9,3,    9,7},
        {6,3,   6,6,    6,7,    6,0,    7,5,    7,4,    6,5},
        {4,2,   4,3,    1,4,    1,5,    1,6,    4,1,    3,6},
        {4,5,   4,6,    1,1,    1,2,    1,3,    4,4,    2,1},
        {3,3,   3,5,    2,5,    2,6,    2,7,    4,7,    2,0},
        {7,6,   6,1,    5,0,    5,2,    5,1,    6,2,    6,4},
};

static int digits[16][7] = {
    {1, 2, 3, 4, 5, 6, 0},  // 0
    {2, 3, 0, 0, 0, 0, 0},  // 1
    {1, 2, 4, 5, 7, 0, 0},  // 2
    {1, 2, 3, 4, 7, 0, 0},  // 3
    {2, 3, 6, 7, 0, 0, 0},  // 4
    {1, 3, 4, 6, 7, 0, 0},  // 5
    {1, 3, 4, 5, 6, 7, 0},  // 6
    {1, 2, 3, 0, 0, 0, 0},  // 7
    {1, 2, 3, 4, 5, 6, 7},  // 8
    {1, 2, 3, 4, 6, 7, 0},  // 9
    {1, 2, 3, 5, 6, 7, 0},  // A
    {3, 4, 5, 6, 7, 0, 0},  // b
    {1, 4, 5, 6, 0, 0, 0},  // c
    {2, 3, 4, 5, 7, 0, 0},  // d
    {1, 4, 5, 6, 7, 0, 0},  // E
    {1, 5, 6, 7, 0, 0, 0}   // F
};

void set_segment(uint8_t *displayData,uint8_t segment_byte, uint8_t segment_bit, uint8_t value)
{
    // depending on whether the display is inverted and the desired value
    // the bit needs to be set or cleared
    if (value == 1){
        displayData[segment_byte] |= (1 << segment_bit);
    }else{
        displayData[segment_byte] &= ~(1 << segment_bit);
    }
}
void clear_digit(uint8_t *displayData,uint8_t where)
{

    int segment_byte;
    int segment_bit;
    for (int i = 0; i < 7; i++)
    {
        // get the segment needed to display the digit 'digit',
        // this is stored in the array 'digits'
        int segment = digits[8][i] - 1;
        // segment = -1 indicates that there are no more segments to display
        if (segment >= 0)
        {
            segment_byte = num_segments[where-1][2 * segment];
            segment_bit = num_segments[where-1][1 + 2 * segment];
            set_segment(displayData, segment_byte, segment_bit, 0);
        }
        else
            // there are no more segments to be displayed
            break;
    }
}


void set_digit(uint8_t *displayData, uint8_t where, uint8_t digit)
{
    // check if the input is valid
    if ((digit >= 0) && (digit < 16) && (where >= 1) && (where <= 13))
    {

        // set the segments, there are up to 11 segments in a digit
        int segment_byte;
        int segment_bit;
        for (int i = 0; i < 7; i++)
        {
            // get the segment needed to display the digit 'digit',
            // this is stored in the array 'digits'
            int segment = digits[digit][i] - 1;
            // segment = -1 indicates that there are no more segments to display
            if (segment >= 0)
            {
                segment_byte = num_segments[where-1][2 * segment];
                segment_bit = num_segments[where-1][1 + 2 * segment];
                set_segment(displayData, segment_byte, segment_bit, 1);
            }
            else
                // there are no more segments to be displayed
                break;
        }
    }
}

void bit9Init(void)
{
    GPIOA_ModeCfg(CS_PIN, GPIO_ModeOut_PP_5mA);
    GPIOA_ModeCfg(SCLK_PIN, GPIO_ModeOut_PP_5mA);
    GPIOA_ModeCfg(MOSI_PIN, GPIO_ModeOut_PP_5mA);
	GPIOA_ModeCfg(BUSY_PIN, GPIO_ModeIN_PU);
	GPIOA_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP_5mA);
	GPIOA_ModeCfg(GPIO_Pin_12, GPIO_ModeOut_PP_5mA);
	CS_H;
	MOSI_H;
	SCLK_L;
	GPIOA_SetBits(GPIO_Pin_11);
	GPIOA_SetBits(GPIO_Pin_12);
}

void bit9WriteCmd(UINT8 u8_writedata)
{
	CS_L;
    MOSI_L;
    SCLK_H;
    SCLK_L;
    for (UINT8 i = 0; i < 8; i++)
    {
        if (u8_writedata & 0x80)
            MOSI_H;
        else
            MOSI_L;
        SCLK_H;
        u8_writedata <<= 1;
        SCLK_L;
    }
		CS_H;
		MOSI_H;
		DelayUs(5);
}

void bit9WriteData(UINT8 u8_writedata)
{
	CS_L;
    MOSI_H;
    SCLK_H;
    SCLK_L;
    for (UINT8 i = 0; i < 8; i++)
    {
        if (u8_writedata & 0x80)
            MOSI_H;
        else
            MOSI_L;
        SCLK_H;
        u8_writedata <<= 1;
        SCLK_L;
    }
		CS_H;
		MOSI_H;
		DelayUs(5);
}

void allWhite(void)
{
	GPIOA_ResetBits(GPIO_Pin_11);       //set low pulse on RST_N for 110ms
	DelayUs(110);
	GPIOA_SetBits(GPIO_Pin_11);
	
	bit9WriteCmd(0x04);                 //send Power On
	
	while (GPIOA_ReadPortPin(BUSY_PIN) == 0)    //Wait for BUSY_N high
        DelayMs(1);
	
	bit9WriteCmd(0x00);                 //Send: Panel Setting (PANEL_SETTING - 0x00)
	bit9WriteData(0x0b);

	bit9WriteCmd(0x01);                 //Send: Power Setting (POWER_SETTING - 0x01)
	bit9WriteData(0x46);
	bit9WriteData(0x46);
	
	bit9WriteCmd(0x03);                 //Send: Power Off Sequence Setting (POWER_OFF_SEQUENCE_SETTING - 0x03)
	bit9WriteData(0x00);
	
	bit9WriteCmd(0x30);                 //Send: Frame Rate Control (FRAME_RATE_CONTROL - 0x30)
	bit9WriteData(0x02);
	
	bit9WriteCmd(0x20);                 //Send: LUTV (0x20)
	for(int i=0;i<15;i++){
	    bit9WriteData(lut_v[i]);
	}

	bit9WriteCmd(0x23);                 //Send:  LUT_KK (0x23)
	for(int i=0;i<15;i++){
	    bit9WriteData(lut_kk[i]);
	}

	bit9WriteCmd(0x26);                 //Send: LUT_WW (0x26)
	for(int i=0;i<15;i++){
	    bit9WriteData(lut_ww[i]);
	}
	
	bit9WriteCmd(0x18);	
	for(int i=0;i<18;i++)
	{
		bit9WriteData(0xff);
	}

	bit9WriteCmd(0x1c);	
	for(int i=0;i<18;i++)
	{
		bit9WriteData(0xff);
	}	
	
	bit9WriteCmd(0x12);	
	
	while (GPIOA_ReadPortPin(BUSY_PIN) == 0)
        DelayMs(1);
	
	bit9WriteCmd(0x02);
  bit9WriteData(0x03);
	
		while (GPIOA_ReadPortPin(BUSY_PIN) == 0)
        DelayMs(1);
}


void displayData(uint8_t *displayData)
{

    bit9WriteCmd(0x04);

    while (GPIOA_ReadPortPin(BUSY_PIN) == 0)
        DelayMs(1);

    bit9WriteCmd(0x00);
    bit9WriteData(0x0b);

    bit9WriteCmd(0x01);
    bit9WriteData(0x46);
    bit9WriteData(0x46);

    bit9WriteCmd(0x03);
    bit9WriteData(0x06);

    bit9WriteCmd(0x30);
    bit9WriteData(0x03);

    bit9WriteCmd(0x15);             //Send (ONLY when not initialising): PARTIAL_DISPLAY_REFRESH - 0x15
    bit9WriteData(0x00);
    bit9WriteData(0x87);
    bit9WriteData(0x01);


    bit9WriteCmd(0x20);
    bit9WriteData(0x86);
    bit9WriteData(0x86);
    bit9WriteData(0x01);
    bit9WriteData(0x46);
    bit9WriteData(0x46);
    bit9WriteData(0x01);
    bit9WriteData(0x86);
    bit9WriteData(0x86);
    bit9WriteData(0x01);
    bit9WriteData(0x46);
    bit9WriteData(0x46);
    bit9WriteData(0x01);
    bit9WriteData(0x81);
    bit9WriteData(0x81);
    bit9WriteData(0x01);

    bit9WriteCmd(0x23);
    bit9WriteData(0x86);
    bit9WriteData(0x86);
    bit9WriteData(0x01);
    bit9WriteData(0x46);
    bit9WriteData(0x46);
    bit9WriteData(0x01);
    bit9WriteData(0x86);
    bit9WriteData(0x86);
    bit9WriteData(0x01);
    bit9WriteData(0x46);
    bit9WriteData(0x46);
    bit9WriteData(0x01);
    bit9WriteData(0x81);
    bit9WriteData(0x81);
    bit9WriteData(0x01);

    bit9WriteCmd(0x24);
    bit9WriteData(0x86);
    bit9WriteData(0x86);
    bit9WriteData(0x01);
    bit9WriteData(0x86);
    bit9WriteData(0x86);
    bit9WriteData(0x01);
    bit9WriteData(0x86);
    bit9WriteData(0x86);
    bit9WriteData(0x01);
    bit9WriteData(0x86);
    bit9WriteData(0x86);
    bit9WriteData(0x01);
    bit9WriteData(0x81);
    bit9WriteData(0x81);
    bit9WriteData(0x01);

    bit9WriteCmd(0x25);
    bit9WriteData(0x46);
    bit9WriteData(0x46);
    bit9WriteData(0x01);
    bit9WriteData(0x46);
    bit9WriteData(0x46);
    bit9WriteData(0x01);
    bit9WriteData(0x46);
    bit9WriteData(0x46);
    bit9WriteData(0x01);
    bit9WriteData(0x46);
    bit9WriteData(0x46);
    bit9WriteData(0x01);
    bit9WriteData(0x81);
    bit9WriteData(0x81);
    bit9WriteData(0x01);

    bit9WriteCmd(0x26);
    bit9WriteData(0x86);
    bit9WriteData(0x86);
    bit9WriteData(0x01);
    bit9WriteData(0x46);
    bit9WriteData(0x46);
    bit9WriteData(0x01);
    bit9WriteData(0x86);
    bit9WriteData(0x86);
    bit9WriteData(0x01);
    bit9WriteData(0x46);
    bit9WriteData(0x46);
    bit9WriteData(0x01);
    bit9WriteData(0x81);
    bit9WriteData(0x81);
    bit9WriteData(0x01);


    bit9WriteCmd(0x18);
    for(int i=0;i<17;i++){
        bit9WriteData(displayData[i]);
    }
    bit9WriteData(0xff);


    bit9WriteCmd(0x12);

    while (GPIOA_ReadPortPin(BUSY_PIN) == 0)
        DelayMs(1);

    bit9WriteCmd(0x02);
    bit9WriteData(0x03);

        while (GPIOA_ReadPortPin(BUSY_PIN) == 0)
        DelayMs(1);
}

void allBlack(void)
{
		GPIOA_ResetBits(GPIO_Pin_11);
		DelayUs(110);
	GPIOA_SetBits(GPIO_Pin_11);
		bit9WriteCmd(0x04);

	while (GPIOA_ReadPortPin(BUSY_PIN) == 0)
        DelayMs(1);
	
	bit9WriteCmd(0x00);
  bit9WriteData(0x0b);

	bit9WriteCmd(0x01);
	bit9WriteData(0x46);
	bit9WriteData(0x46);
	
	bit9WriteCmd(0x03);
	bit9WriteData(0x00);
	
	bit9WriteCmd(0x30);
	bit9WriteData(0x02);

    bit9WriteCmd(0x20);                 //Send: LUTV (0x20)
    for(int i=0;i<15;i++){
        bit9WriteData(lut_v[i]);
    }

    bit9WriteCmd(0x23);                 //Send:  LUT_KK (0x23)
    for(int i=0;i<15;i++){
        bit9WriteData(lut_kk[i]);
    }

    bit9WriteCmd(0x26);                 //Send: LUT_WW (0x26)
    for(int i=0;i<15;i++){
        bit9WriteData(lut_ww[i]);
    }
	
	bit9WriteCmd(0x18);	
	for(int i=0;i<18;i++)
	{
		bit9WriteData(0x00);
	}

	bit9WriteCmd(0x1c);	
	for(int i=0;i<18;i++)
	{
		bit9WriteData(0x00);
	}	
	
	bit9WriteCmd(0x12);	
	
	while (GPIOA_ReadPortPin(BUSY_PIN) == 0)
        DelayMs(1);
	
	bit9WriteCmd(0x02);
  bit9WriteData(0x03);
	
		while (GPIOA_ReadPortPin(BUSY_PIN) == 0)
        DelayMs(1);
}
